﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ServiceModel;
using System.ServiceModel.Activation;
using Esb.Soa.Contract;
using System.ServiceModel.Web;
using Esb.Soa.Domain.Monitor;
using Esb.Soa.Domain.Factories;
using Esb.Soa.Domain.ServiceHandlers;
using Esb.Domain.DomainObjects;

namespace Esb.SoaHost.Service
{
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class CallService
    {
        static CallService()
        {
            //TODO:启动时同时启动监控、告警进程
            ServiceAlert alert = new ServiceAlert();
            alert.Start();
        }
        /// <summary>
        /// 调用服务
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [WebInvoke(UriTemplate = "CallServiceByEsb", Method = "POST")]
        public CallServiceResponse CallServiceByEsb(CallServiceRequest request)
        {
            ServiceMonitor monitor = new ServiceMonitor(request.ServiceRouteName + "." + request.ServiceEntity +
                "." + request.Method, request.CallerId);
            CallServiceResponse response = new CallServiceResponse { };

            try
            {
                monitor.SetStartTime();
                monitor.TraficRequest = request.RequestBody.Length * 2;//流量统计

                #region 初始化服务调用
                ServiceCall call = new ServiceCall();
                call.ConsumerId = request.CallerId;

                DateTime dt1 = DateTime.Now;
                string errorMsg = "";
                bool isReady = call.Initialize(request.ServiceRouteName, request.ServiceEntity, request.Method,
                    (Esb.Domain.DomainObjects.EnvironmentType)(int)request.Environment,
                    request.ServiceUrl, 0, out errorMsg);
                DateTime dt2 = DateTime.Now;
                monitor.Time1 = (int)(dt2 - dt1).TotalMilliseconds;

                //有关服务尚未注册
                if (!isReady)
                {
                    response.ReturnMessage = new Message();
                    response.ReturnMessage.Code = "1";
                    response.ReturnMessage.MessageText = errorMsg;
                    //response.messageDTO.messageText = "服务尚未注册或不存在，或者此服务不适用于此环境";
                    return response;
                }

                //服务提供者的Id
                response.ServiceApplicationId = call.Service.ApplicationId;
                monitor.ServiceApplicationId = call.Service.ApplicationId;

                IServiceHandler serviceHandler = GetServiceHandler(call.Arch, call.ServiceUrl, request.HttpVerb);
                call.ServiceHandler = serviceHandler;
                #endregion

                string responseBody = call.Call(request.RequestBody);
                DateTime dt3 = DateTime.Now;
                monitor.Time2 = (int)(dt3 - dt2).TotalMilliseconds;

                response.ResponseBody = responseBody;
                response.ReturnMessage = new Message();
                response.ReturnMessage.Code = "0";
                monitor.TraficReponse = responseBody.Length * 2;//流量统计
                //无法判断是否真的调用成功，如果客户服务返回异常信息的话，也无法判断，所以不能依赖esb来判断服务内部的故障

                monitor.IsSuccess = true;
                return response;
            }
            catch (Exception e)
            {
                monitor.SetException(e);
                //记录异常信息
                monitor.IsSuccess = false;

                response.ReturnMessage = new Message();
                response.ReturnMessage.Code = "1";
                response.ReturnMessage.MessageText = e.Message;
                return response;
            }
            finally
            {
                monitor.SetEndTime();
                monitor.RecordServiceCall();
                //记录调用的日志
            }
        }

        /// <summary>
        /// 工厂方法，根据.Net/Java平台取不同的处理器
        /// </summary>
        /// <param name="platform"></param>
        /// <returns></returns>
        private IServiceHandler GetServiceHandler(string arch, string url, string verb)
        {
            if (arch == "Rest")
            {
                RestServiceHandler handler = new RestServiceHandler();
                handler.HttpVerb = verb;
                return handler;
            }
            //else if (platform == ".Net")
            //{
            //    return new NetServiceHandler();
            //}
            //else if (platform == "Java")
            //{
            //    return new JavaServiceHandler();
            //}
            else
            {
                return new WebServiceHandler();
            }
        }
    }
}